package org.example.guice;

import lombok.Getter;
import org.example.asm.ClassVisitor;
import org.example.asm.Opcodes;

import java.util.LinkedHashSet;
import java.util.Set;


/**
 * ASM class visitor
 */
@Getter
final class SimpleAnnotationMetadataReadingVisitor extends ClassVisitor {


    private int access;

    private String className = "";

    private String superClassName;

    private String enclosingClassName;

    private boolean independentInnerClass;

    private String[] interfaceNames = new String[0];

    private Set<String> memberClassNames = new LinkedHashSet<>(4);


    SimpleAnnotationMetadataReadingVisitor() {
        super(Opcodes.ASM7);
    }


    @Override
    public void visit(int version, int access, String name, String signature,
                      String superName, String[] interfaces) {

        this.className = toClassName(name);
        this.access = access;
        if (superName != null && !isInterface(access)) {
            this.superClassName = toClassName(superName);
        }
        this.interfaceNames = new String[interfaces.length];
        for (int i = 0; i < interfaces.length; i++) {
            this.interfaceNames[i] = toClassName(interfaces[i]);
        }
    }

    private boolean isInterface(int access) {
        return (access & Opcodes.ACC_INTERFACE) != 0;
    }

    @Override
    public void visitOuterClass(String owner, String name, String desc) {
        this.enclosingClassName = toClassName(owner);
    }

    @Override
    public void visitInnerClass(String name, String outerName, String innerName, int access) {
        if (outerName != null) {
            String className = toClassName(name);
            String outerClassName = toClassName(outerName);
            if (this.className.equals(className)) {
                this.enclosingClassName = outerClassName;
                this.independentInnerClass = ((access & Opcodes.ACC_STATIC) != 0);
            } else if (this.className.equals(outerClassName)) {
                this.memberClassNames.add(className);
            }
        }
    }

    private String toClassName(String name) {
        return name.replace("/", ".");
    }


}
